#ifndef __SubEntity_H__
#define __SubEntity_H__

#include "defines.h"
#include "video/SubMesh.h"
#include "video/Array.h"
#include "video/Skeleton.h"
#include "video/Animation.h"
#include "video/MeshAnimation.h"
#include <vector>

#define MaxVertexWeight					4
#define BlendMatrixIdx(w, x, y, z)		D3DCOLOR_ARGB(w, x, y, z)

namespace KEngine
{

class Device;
class SubEntity
{
public:
	struct VERTEX
	{
	public:
		D3DXVECTOR3			pos;
		D3DXVECTOR3			normal;
		D3DXVECTOR2			tex;

		static const DWORD FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
	};

	struct BLENDVERTEX
	{
	public:
		D3DXVECTOR3			pos;
		float				weights[MaxVertexWeight - 1];
		DWORD				matrixIndices;
		D3DXVECTOR3			normal;
		D3DXVECTOR2			tex;

		static const DWORD FVF = D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4 | D3DFVF_NORMAL | D3DFVF_TEX1;
	};

public:
	SubEntity(SubMesh* subMesh);
	virtual ~SubEntity();

	bool		initialise();
	void		updateVertexBuffer(bool forceCreate = false);

	void		update(const AnimationState& as);
	void		render(float alpha);

	SubMesh*	getSubMesh();
	void		setAnimation(SubMeshAnimation* sma);

	void		_notifySkeletonAttached(Skeleton* skeleton);

protected:
	void		doMeshAnimation(const AnimationState& as);
	void		doSkeletalAnimation();

protected:
	SubMesh*					mSubMesh;

	ID3DVertexBuffer*		mpVertexBuffer;
	
	// Due to the differences between normal VERTEX and blend VERTEX, we need to use
	// two sets of variables to record the vertices. Doing this likely won't affect
	// the performance of simple sample but it should be done in complex engine.
	Array<VERTEX>				mVertices;
	Array<BLENDVERTEX>			mBlendVertices;
	void*						mBuffPtr;
	DWORD						mFVF;
	unsigned int				mVertexSize;
	int							mNumVertices;

	SubMeshAnimation*			mAnimation;
	Device*						mDevice;
};

typedef std::vector<SubEntity*> SubEntityList;
typedef std::vector<SubEntity*>::iterator ElSubEntityIterator;

}

#endif 